#include "Chat.h"
#include "messages/TransportMessage.h"
#include "messages/ExtendedChatMessage.h"
#include "messages/ChatAck.h"
#include "User.h"
#include "UI_multiplexer.h"

Chat::Chat(Userdatabase* users, Transport* transport):
    users(users), transport(transport)
{
    transport->register_message_handler(this, TransportMessage::CHAT);
    this->ui = &UI_multiplexer::instance(); //FIXME always use singleton
}

Chat::~Chat()
{
    transport->register_message_handler(NULL, TransportMessage::CHAT);
}

void Chat::handleMessage(
        TransportMessage& msg,
        TransportMessage::MESSAGE_TYPE type,
        uint8_t subtype,
        UserPtr user
    )
{
    assert(type == TransportMessage::CHAT);
    
    switch (subtype)
    {
        case Chat::MESSAGE:
        {
            auto_ptr<ExtendedChatMessage> chatmsg(
                    msg.decapsulate<ExtendedChatMessage>());
            chatmsg->from = user->get_name();
            chatmsg->to = users->get_myself()->get_name();
            
            if (ui)
            {
                ui->write_to_user(chatmsg->getXml());
                
                ChatAck ack(chatmsg->messageId);
                transport->send_to(
                        ack,
                        TransportMessage::CHAT,
                        Chat::ACK,
                        user);
            }
        }
        break;
        
        case Chat::ACK:
        {
            auto_ptr<ChatAck> ack(msg.decapsulate<ChatAck>());
            ack->chat_to = user->get_name();
            
            if (ui)
            {
                ui->write_to_user(ack->getXml());
            }
        }
        break;
        
        default:
            // Ignore unknown messages
        break;
    }
}

void Chat::send_chat(ptree& command_pt, Useroutputinterface& sending_ui)
{
    ExtendedChatMessage msg;
    
    msg.from = users->get_myself()->get_name();
    msg.parseXml(command_pt);

    UserPtr dest = users->getUser(msg.to);
    if (dest)
    {
        // Send echo to all UIs
        if (ui)
        {
            ui->write_to_user(msg.getXml(true));
        }
        
        transport->send_to(
                msg,
                TransportMessage::CHAT,
                Chat::MESSAGE,
                dest);
    } else {
        sending_ui.write_to_user(
                "NO USER called '" + msg.to + "' in database.");
    }
}


